package com.xjx.programmer.service;

import com.xjx.programmer.model.DatabaseConnection;
import com.xjx.programmer.model.ExecuteResult;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.apache.http.HttpHost;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Elasticsearch 数据库服务
 */
@Slf4j
@Service
public class ElasticsearchService {

    /**
     * 创建 Elasticsearch 客户端
     */
    public RestHighLevelClient createClient(DatabaseConnection connection) {
        HttpHost host = new HttpHost(connection.getHost(), connection.getPort(), "http");
        RestClientBuilder builder = RestClient.builder(host);
        
        // 如果需要认证，可以添加认证配置
        if (connection.getUsername() != null && !connection.getUsername().isEmpty()) {
            // 这里可以添加认证配置，根据实际的 Elasticsearch 版本和认证方式
            // 例如：Basic 认证、API Key 等
        }
        
        return new RestHighLevelClient(builder);
    }

    /**
     * 执行 Elasticsearch 查询
     */
    public ExecuteResult executeQuery(DatabaseConnection connection, String index, String query) {
        long startTime = System.currentTimeMillis();
        
        try (RestHighLevelClient client = createClient(connection)) {
            if (client == null) {
                return ExecuteResult.builder()
                        .success(false)
                        .message("Elasticsearch 客户端未配置")
                        .executeTime(System.currentTimeMillis() - startTime)
                        .errorMessage("请先配置 Elasticsearch 客户端")
                        .build();
            }
            
            SearchRequest searchRequest = new SearchRequest(index);
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            
            // 解析查询条件
            if (query != null && !query.trim().isEmpty()) {
                searchSourceBuilder.query(QueryBuilders.queryStringQuery(query));
            } else {
                searchSourceBuilder.query(QueryBuilders.matchAllQuery());
            }
            
            searchRequest.source(searchSourceBuilder);
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            
            List<Map<String, Object>> data = new ArrayList<>();
            for (SearchHit hit : searchResponse.getHits().getHits()) {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                sourceAsMap.put("_id", hit.getId());
                sourceAsMap.put("_score", hit.getScore());
                data.add(sourceAsMap);
            }
            
            return ExecuteResult.builder()
                    .success(true)
                    .message("查询成功")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .data(data)
                    .build();
                    
        } catch (IOException e) {
            log.error("执行 Elasticsearch 查询失败: index={}, query={}", index, query, e);
            return ExecuteResult.builder()
                    .success(false)
                    .message("查询失败")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .errorMessage(e.getMessage())
                    .errorStack(e.getStackTrace().toString())
                    .build();
        }
    }

    /**
     * 创建索引
     */
    public ExecuteResult createIndex(DatabaseConnection connection, String indexName, String mapping) {
        long startTime = System.currentTimeMillis();
        
        try (RestHighLevelClient client = createClient(connection)) {
            if (client == null) {
                return ExecuteResult.builder()
                        .success(false)
                        .message("Elasticsearch 客户端未配置")
                        .executeTime(System.currentTimeMillis() - startTime)
                        .errorMessage("请先配置 Elasticsearch 客户端")
                        .build();
            }
            
            CreateIndexRequest request = new CreateIndexRequest(indexName);
            if (mapping != null && !mapping.trim().isEmpty()) {
                request.mapping(mapping, XContentType.JSON);
            }
            
            client.indices().create(request, RequestOptions.DEFAULT);
            
            return ExecuteResult.builder()
                    .success(true)
                    .message("索引创建成功")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .build();
                    
        } catch (IOException e) {
            log.error("创建 Elasticsearch 索引失败: index={}", indexName, e);
            return ExecuteResult.builder()
                    .success(false)
                    .message("索引创建失败")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .errorMessage(e.getMessage())
                    .errorStack(e.getStackTrace().toString())
                    .build();
        }
    }

    /**
     * 删除索引
     */
    public ExecuteResult deleteIndex(DatabaseConnection connection, String indexName) {
        long startTime = System.currentTimeMillis();
        
        try (RestHighLevelClient client = createClient(connection)) {
            if (client == null) {
                return ExecuteResult.builder()
                        .success(false)
                        .message("Elasticsearch 客户端未配置")
                        .executeTime(System.currentTimeMillis() - startTime)
                        .errorMessage("请先配置 Elasticsearch 客户端")
                        .build();
            }
            
            DeleteIndexRequest request = new DeleteIndexRequest(indexName);
            client.indices().delete(request, RequestOptions.DEFAULT);
            
            return ExecuteResult.builder()
                    .success(true)
                    .message("索引删除成功")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .build();
                    
        } catch (IOException e) {
            log.error("删除 Elasticsearch 索引失败: index={}", indexName, e);
            return ExecuteResult.builder()
                    .success(false)
                    .message("索引删除失败")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .errorMessage(e.getMessage())
                    .errorStack(e.getStackTrace().toString())
                    .build();
        }
    }

    /**
     * 插入文档
     */
    public ExecuteResult insertDocument(DatabaseConnection connection, String index, String id, String document) {
        long startTime = System.currentTimeMillis();
        
        try (RestHighLevelClient client = createClient(connection)) {
            if (client == null) {
                return ExecuteResult.builder()
                        .success(false)
                        .message("Elasticsearch 客户端未配置")
                        .executeTime(System.currentTimeMillis() - startTime)
                        .errorMessage("请先配置 Elasticsearch 客户端")
                        .build();
            }
            
            IndexRequest request = new IndexRequest(index);
            if (id != null && !id.trim().isEmpty()) {
                request.id(id);
            }
            request.source(document, XContentType.JSON);
            
            IndexResponse response = client.index(request, RequestOptions.DEFAULT);
            
            return ExecuteResult.builder()
                    .success(true)
                    .message("文档插入成功")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .affectedRows(1)
                    .build();
                    
        } catch (IOException e) {
            log.error("插入 Elasticsearch 文档失败: index={}, id={}, document={}", index, id, document, e);
            return ExecuteResult.builder()
                    .success(false)
                    .message("文档插入失败")
                    .executeTime(System.currentTimeMillis() - startTime)
                    .errorMessage(e.getMessage())
                    .errorStack(e.getStackTrace().toString())
                    .build();
        }
    }

    /**
     * 测试数据库连接
     */
    public boolean testConnection(DatabaseConnection connection) {
        try (RestHighLevelClient client = createClient(connection)) {
            if (client == null) {
                return false;
            }
            // 执行 ping 操作测试连接
            return client.ping(RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("测试 Elasticsearch 连接失败", e);
            return false;
        }
    }
}
